home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / ICMP.C < prev    next >
C/C++ Source or Header  |  1988-07-28  |  5KB  |  189 lines

  1. /* Internet Control Message Protocol */
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "internet.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "icmp.h"
  9.  
  10. struct icmp_errors icmp_errors;
  11. struct icmp_stats icmp_stats;
  12.  
  13. /* Process an incoming ICMP packet */
  14. void
  15. icmp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  16. struct mbuf *bp;    /* Pointer to ICMP message */
  17. char protocol;        /* Should always be ICMP_PTCL */
  18. int32 source;        /* Sender of ICMP message */
  19. int32 dest;        /* Us */
  20. char tos;        /* Type of Service */
  21. int16 length;        /* Length of ICMP message */
  22. char rxbroadcast;
  23. {
  24.     struct mbuf *htonicmp();
  25.     struct icmp icmp;    /* ICMP header */
  26.     struct ip ip;        /* Offending datagram header */
  27.     int16 type;        /* Type of ICMP message */
  28.     extern int pingflag;    /* DG2KK */
  29.  
  30.     if(rxbroadcast){
  31.         /* Broadcast ICMP packets are to be IGNORED !! */
  32.         icmp_errors.bdcsts++;
  33.         free_p(bp);
  34.         return;
  35.     }
  36.     if(cksum(NULLHEADER,bp,length) != 0){
  37.         /* Bad ICMP checksum; discard */
  38.         icmp_errors.checksum++;
  39.         free_p(bp);
  40.         return;
  41.     }
  42.     ntohicmp(&icmp,&bp);
  43.  
  44.     /* Process the message. Some messages are passed up to the protocol
  45.      * module for handling, others are handled here.
  46.      */
  47.     type = icmp.type & 0xff;
  48.     if(type < ICMP_TYPES)
  49.         icmp_stats.input[type]++;
  50.  
  51.     switch(type){
  52.     case TIME_EXCEED:    /* Time-to-live Exceeded */
  53.     case DEST_UNREACH:    /* Destination Unreachable */
  54.     case QUENCH:        /* Source Quench */
  55.         ntohip(&ip,&bp);    /* Extract offending IP header */
  56.         switch(ip.protocol){
  57.         case TCP_PTCL:
  58.             tcp_icmp(ip.source,ip.dest,icmp.type,icmp.code,&bp);
  59.             break;
  60.         }
  61.         break;
  62.     case ECHO:        /* Echo Request */
  63.         /* Change type to ECHO_REPLY, recompute checksum,
  64.          * and return datagram.
  65.          */
  66.         /* DG2KK: don't send an ECHO_REPLY if pingflag is 'off' */
  67.         if(pingflag == 0)
  68.             return;
  69.         icmp.type = ECHO_REPLY;
  70.         bp = htonicmp(&icmp,bp);
  71.         icmp_stats.output[ECHO_REPLY]++;
  72.         ip_send(dest,source,ICMP_PTCL,tos,0,bp,length,0,0);
  73.         return;
  74.     case REDIRECT:        /* Redirect */
  75.     case PARAM_PROB:    /* Parameter Problem */
  76.         break;
  77.     case ECHO_REPLY:    /* Echo Reply */
  78.         echo_proc(source,dest,&icmp);
  79.         break;
  80.     case TIMESTAMP:        /* Timestamp */
  81.     case TIME_REPLY:    /* Timestamp Reply */
  82.     case INFO_RQST:        /* Information Request */
  83.     case INFO_REPLY:    /* Information Reply */
  84.         break;
  85.     }
  86.     free_p(bp);
  87. }
  88. /* Return an ICMP response to the sender of a datagram */
  89. icmp_output(ip,bp,type,code,args)
  90. struct ip *ip;        /* Header of offending datagram */
  91. struct mbuf *bp;    /* Data portion of datagram */
  92. char type,code;        /* Codes to send */
  93. union icmp_args *args;
  94. {
  95.     struct mbuf *htonicmp();
  96.     struct mbuf *htonip();
  97.     struct icmp icmp;    /* ICMP protocol header */
  98.     int16 dlen;        /* Length of data portion of offending pkt */
  99.     int16 length;        /* Total length of reply */
  100.     extern int32 ip_addr;    /* Our IP address */
  101.  
  102.     if(ip == NULLIP)
  103.         return;
  104.     if(type < ICMP_TYPES)
  105.         icmp_stats.output[type]++;
  106.  
  107.     if(ip->protocol == ICMP_PTCL){
  108.         /* Never send an ICMP message about another ICMP message */
  109.         icmp_errors.noloop++;
  110.         return;
  111.     }
  112.     /* Compute amount of original datagram to return.
  113.      * We return the original IP header, and up to 8 bytes past that.
  114.      */
  115.     dlen = min(8,len_mbuf(bp));
  116.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  117.     if(bp != NULLBUF){
  118.         /* Take excerpt from data portion */
  119.         bp = copy_p(bp,dlen);
  120.     }
  121.     /* Recreate and tack on offending IP header */
  122.     bp = htonip(ip,bp);
  123.  
  124.     icmp.type = type;
  125.     icmp.code = code;
  126.     switch(icmp.type){
  127.     case PARAM_PROB:
  128.         icmp.args.pointer = args->pointer;
  129.         break;
  130.     case REDIRECT:
  131.         icmp.args.address = args->address;
  132.         break;
  133.     case ECHO:
  134.     case ECHO_REPLY:
  135.     case INFO_RQST:
  136.     case INFO_REPLY:
  137.     case TIMESTAMP:
  138.     case TIME_REPLY:
  139.         icmp.args.echo.id = args->echo.id;
  140.         icmp.args.echo.seq = args->echo.seq;
  141.         break;
  142.     default:
  143.         icmp.args.unused = 0;
  144.         break;
  145.     }
  146.     bp = htonicmp(&icmp,bp);    /* Now stick on the ICMP header */
  147.  
  148.     ip_send(ip_addr,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  149. }
  150. /* Generate ICMP header in network byte order, link data, compute checksum */
  151. struct mbuf *
  152. htonicmp(icmp,data)
  153. struct icmp *icmp;
  154. struct mbuf *data;
  155. {
  156.     struct mbuf *rval;
  157.     register char *cp;
  158.     int16 checksum;
  159.  
  160.     rval = alloc_mbuf(ICMPLEN);
  161.     rval->cnt = ICMPLEN;
  162.     cp = rval->data;
  163.  
  164.     *cp++ = icmp->type;
  165.     *cp++ = icmp->code;
  166.     cp = put16(cp,0);        /* Clear checksum */
  167.     cp = put16(cp,icmp->args.echo.id);
  168.     cp = put16(cp,icmp->args.echo.seq);
  169.  
  170.     /* Link in data, compute checksum, and stash result */
  171.     rval->next = data;
  172.     checksum = cksum(NULLHEADER,rval,len_mbuf(rval));
  173.     cp = &rval->data[2];
  174.     cp = put16(cp,checksum);
  175.  
  176.     return rval;
  177. }
  178. /* Pull off ICMP header */
  179. ntohicmp(icmp,bpp)
  180. struct icmp *icmp;
  181. struct mbuf **bpp;
  182. {
  183.     icmp->type = pullchar(bpp);
  184.     icmp->code = pullchar(bpp);
  185.     (void) pull16(bpp);        /* Toss checksum */
  186.     icmp->args.echo.id = pull16(bpp);
  187.     icmp->args.echo.seq = pull16(bpp);
  188. }
  189.